package org.example.Tool.Component;

import org.example.dataHandle.DataGroup;

import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import java.awt.*;
import java.util.Iterator;

public class CustomGraph extends JPanel{
    //protected Rectangle rectangle;
    protected final DataGroup<? extends Number> dataSource;

    protected long division = 1;

    public CustomGraph(DataGroup<? extends Number> datasource){
        this.setPreferredSize(new Dimension(500,300));
        this.dataSource = datasource;
        determineDivision();
        ui = new ComponentUI() {
            @Override
            public void paint(Graphics g, JComponent c) {
                Point testPoint = new Point(40,30);
                drawGraph(g,testPoint);
                drawEdge(g,testPoint);
                drawNumber(g,new Point(testPoint.x, (int)CustomGraph.this.getSize().getHeight() - testPoint.y - 20));
            }
        };
    }

    protected void determineDivision(){
        long expect = dataSource.getTimeRange() / 4;
        while(division < expect){
            division *= 5;
            if(division >= expect){
                if(division / 2 >= expect)
                    division = division / 5 * 2;
                break;
            }
            division *= 2;
        }
    }

    protected void drawGraph(Graphics g, Point StartPos){
        this.setBackground(Color.LIGHT_GRAY);
        Dimension StartSize = new Dimension(
                this.getWidth() - (StartPos.x * 2),
                this.getHeight() - (StartPos.y * 2)
        );
        Color storeColor = g.getColor();
        g.setColor(Color.RED);
        synchronized (dataSource) {
            if (dataSource.isEmpty())
                return;
            int leftValue;
            int leftTime;
            int timeStart;
            double rate1;
            double rate2;
            Iterator<? extends DataGroup.Pair<? extends Number,Long>> it = dataSource.getIterator();
            {
                DataGroup.Pair<? extends Number, Long> tempPair = it.next();
                leftValue = tempPair.getFirst().intValue();
                leftTime = tempPair.getSecond().intValue();
                timeStart = leftTime;
            }
            rate1 = StartSize.getHeight() / dataSource.getMaxValue().doubleValue() * 0.8;
            rate2 = StartSize.getWidth() / dataSource.getTimeRange();

            while (it.hasNext()) {
                DataGroup.Pair<? extends Number, Long> tempPair = it.next();
                g.drawLine(
                        (int) (StartPos.x + (leftTime - timeStart) * rate2),
                        (int) (StartPos.y + StartSize.getHeight() - (leftValue * rate1)),
                        (int) (StartPos.x + (tempPair.getSecond() - timeStart) * rate2),
                        (int) (StartPos.y +  StartSize.getHeight() - (tempPair.getFirst().intValue() * rate1))
                );
                leftValue = tempPair.getFirst().intValue();
                leftTime = tempPair.getSecond().intValue();
            }
        }
        g.setColor(storeColor);
    }

    protected void drawEdge(Graphics g, Point StartPos){
        Color storeColor = g.getColor();
        g.setColor(Color.BLACK);
        g.drawRect(
                StartPos.x,
                StartPos.y,
                this.getWidth() - (StartPos.x * 2),
                this.getHeight() - (StartPos.y * 2)
        );
        g.setColor(storeColor);
    }

    protected void drawNumber(Graphics g, Point StartPos){
        Color storeColor = g.getColor();
        Dimension StartSize = new Dimension(
                this.getWidth() - (StartPos.x * 2),
                this.getHeight() - (StartPos.y * 2)
        );
        g.setColor(Color.red);
        long range;
        long front;
        synchronized (dataSource){
            if(dataSource.getLatest() == null)
                return;
            range = dataSource.getTimeRange();
            front = dataSource.getFront().getSecond();
        }
        long back = front + range;
        long i = back / division;
        while(i > 0){
            long renderPoint = i * division;
            if(renderPoint <= front)
                return;
            String printNum;
            if(renderPoint < 100000)
                printNum = renderPoint + "ms";
            else if(renderPoint < 600000)
                printNum = (renderPoint / 1000) + "s";
            else {
                printNum = String.format("%.2f",((float)renderPoint / 60000)) + "min";
            }
            g.drawString(
                    printNum,
                    (int) (StartPos.x + StartSize.getWidth() * (renderPoint - front) / range),
                    StartPos.y
                    );
            i--;
        }
        g.setColor(storeColor);
    }
}
